package com.jc.repository.generator.utils;

import com.jc.base.Assert;
import com.jc.base.ComponentException;
import com.jc.repository.generator.annotation.NotNull;
import com.jc.utils.Strings;
import org.apache.commons.lang3.StringUtils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author wangli
 * @create 2016-09-14 17:07
 * @description 生成mybatis代码的实用工具类, 利用反射,构造条件
 */

public class GenerateMybaitsUtils {


    /**
     * 用于检查
     *
     * @param object
     * @throws Exception date 2016年09月14日17:04:36
     */
    public static void checkNotNull(Object object) {

        Field[] fields = object.getClass().getDeclaredFields();

        for (int j = fields.length - 1; j >= 0; j--) {
            Field field = fields[j];
            fields[j].setAccessible(true);
            NotNull annotation = field.getAnnotation(NotNull.class);

            if (annotation == null || field.getName().equals("id")) {
                continue;
            }

            try {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), object.getClass());
                Method method = pd.getReadMethod();

                Object val = method.invoke(object);
                System.out.println("name : " + field.getName() + " = " + val);

                if (field.getType().equals(String.class)) {
                    Assert.isTrue(Strings.isNotEmpty((String) val), "用于保存的" + field.getName() + "不能为空");
                } else {
                    Assert.notNull(val, "用于保存的" + field.getName() + "不能为空");
                }

            } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
                e.printStackTrace();
                throw new ComponentException(ComponentException.ErrCode.系统异常, "校验异常");
            }

        }
    }

    /**
     * 利用反射, 构造 andEuqualTo 条件
     *
     * @param criteria domain的condition.criteria类
     * @param domain   传入的domain
     *                 date - 2016年09月16日
     */
    public static void buildConditionsByReflect(Object criteria, Object domain) {

        buildConditionEx(criteria, domain, Condition.andEqualTo);
    }


    /**
     * 根据条件查询, 只能构造一个条件
     *
     * @param criteria
     * @param domain
     * @param condition
     */
    public static void buildConditionEx(Object criteria, Object domain, Condition condition) {

        Field[] fields = domain.getClass().getDeclaredFields();

        for (Field field : fields) {
            String varName = field.getName();

            try {

                boolean accessFlag = field.isAccessible();
                if (!accessFlag) field.setAccessible(Boolean.TRUE);
                field.setAccessible(Boolean.TRUE);

                Object varValue = field.get(domain);
                //筛选出domain里面,非空字段,以及serialVersionUID字段
                if (null != varValue && !varName.contains("serialVersionUID")) {

                    String sb;
                    if (condition != null) {
                        sb = new StringBuilder().append("and").append(StringUtils.capitalize(varName)).append(condition.getBuild()).toString();
                    } else {
                        sb = new StringBuilder().append("and").append(StringUtils.capitalize(varName)).append("EqualTo").toString();

                    }
                    Method[] methods = criteria.getClass().getMethods();

                    for (Method method : methods) {
                        String methodName = method.getName();
                        //执行criteria.and***EqualTo(***)方法
                        //例如 criteria.andOptTagEqualTo(tag);
                        if (methodName.contains(sb)) {
                            if (condition == Condition.andIsNotNull || condition == Condition.andIsNull) {
                                method.invoke(criteria);
                            } else {
                                method.invoke(criteria, varValue);
                            }
                            break;
                        }
                    }

                }

                if (!accessFlag) field.setAccessible(false);

            } catch (Exception e) {
                e.printStackTrace();
                throw new ComponentException(ComponentException.ErrCode.系统异常, "构造查询条件异常");
            }

        }
    }

    /**
     * 构造多个条件,
     *
     * @param criteria
     * @param conditionsExtend
     */
    public static void buildConditionExs(Object criteria, ConditionsExtend conditionsExtend) {

        if (conditionsExtend.getAndIsNull() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndIsNull(), Condition.andIsNull);
        }

        if (conditionsExtend.getAndIsNotNull() != null) {

            buildConditionEx(criteria, conditionsExtend.getAndIsNotNull(), Condition.andIsNotNull);
        }

        if (conditionsExtend.getAndEqualTo() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndEqualTo(), Condition.andEqualTo);
        }

        if (conditionsExtend.getAndNotEqualTo() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndNotEqualTo(), Condition.andNotEqualTo);
        }

        if (conditionsExtend.getAndGreaterThan() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndGreaterThan(), Condition.andGreaterThan);
        }

        if (conditionsExtend.getAndGreaterThanOrEqualTo() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndGreaterThanOrEqualTo(), Condition.andGreaterThanOrEqualTo);
        }

        if (conditionsExtend.getAndLessThan() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndLessThan(), Condition.andLessThan);
        }

        if (conditionsExtend.getAndLessThanOrEqualTo() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndLessThanOrEqualTo(), Condition.andLessThanOrEqualTo);
        }

        if (conditionsExtend.getAndLike() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndLike(), Condition.andLike);
        }

        if (conditionsExtend.getAndNotLike() != null) {
            buildConditionEx(criteria, conditionsExtend.getAndNotLike(), Condition.andNotLike);
        }

    }

}
